// WindowManager.java - 简化版本
package org.zjx.manager;

import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.zjx.core.IWindow;
import org.zjx.core.impl.GameWindow;
import org.zjx.core.impl.LoginWindow;
import org.zjx.core.impl.StartWindow;
import org.zjx.util.HwndUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 窗口管理器 - 简化版本：只管启动和监控
 */
@Slf4j
public class WindowManager {
    private static final String WINDOW_CLASS_GAME = "WSGAME";
    private static final String GAME_TITLE = "梦幻西游 ONLINE";

    private static final long MONITOR_INTERVAL = 5;
    private static final long CREATION_COOLDOWN_MS = 3000;

    private static volatile WindowManager instance;
    private static final Object instanceLock = new Object();

    private final List<IWindow> managedWindows = Collections.synchronizedList(new ArrayList<>());
    private final int targetWindowCount;
    private final String gameExePath;
    private final ScheduledExecutorService monitorExecutor;
    private final AtomicBoolean isMonitoring = new AtomicBoolean(false);

    // 简化控制变量
    private final AtomicBoolean isCreating = new AtomicBoolean(false);
    private final AtomicLong lastCreationTime = new AtomicLong(0);

    private WindowManager(int targetWindowCount, String gameExePath) {
        if (targetWindowCount <= 0) {
            throw new IllegalArgumentException("目标窗口数量必须大于0");
        }
        if (gameExePath == null || gameExePath.trim().isEmpty()) {
            throw new IllegalArgumentException("游戏路径不能为空");
        }

        this.targetWindowCount = targetWindowCount;
        this.gameExePath = gameExePath;
        this.monitorExecutor = Executors.newSingleThreadScheduledExecutor(r -> new Thread(r, "WindowMonitor"));

        Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown, "WindowManager-ShutdownHook"));
    }

    public static WindowManager getInstance(int targetWindowCount, String gameExePath) {
        if (instance == null) {
            synchronized (instanceLock) {
                if (instance == null) {
                    instance = new WindowManager(targetWindowCount, gameExePath);
                }
            }
        }
        return instance;
    }

    public static WindowManager getInstance() {
        if (instance == null) {
            throw new IllegalStateException("WindowManager 未初始化");
        }
        return instance;
    }

    /**
     * 初始化已存在的窗口
     */
    public void initializeExistingWindows() {
        log.info("[WindowManager] 开始初始化已存在的窗口");

        // 查找已存在的游戏窗口
        List<WinDef.HWND> existingGameWindows = HwndUtil.findWindows(WINDOW_CLASS_GAME, null);
        log.info("[WindowManager] 发现 {} 个已存在的游戏窗口", existingGameWindows.size());

        for (WinDef.HWND hwnd : existingGameWindows) {
            try {
                if (!isValidGameWindow(hwnd)) {
                    continue;
                }

                String windowTitle = HwndUtil.getWindowTitle(hwnd);
                IWindow window;

                // 根据窗口标题判断窗口类型
                if (windowTitle != null && !windowTitle.contains("[")) {
                    window = new LoginWindow(hwnd);
                } else {
                    window = new GameWindow(hwnd);
                }

                managedWindows.add(window);
                log.info("[WindowManager] 已添加现有窗口: {}", window.getId());

            } catch (Exception e) {
                log.error("[WindowManager] 添加现有窗口失败: {}", hwnd, e);
            }
        }

        log.info("[WindowManager] 初始化完成，当前窗口数量: {}", managedWindows.size());
    }

    /**
     * 启动窗口监控
     */
    public void startMonitoring() {
        if (isMonitoring.getAndSet(true)) {
            log.info("[WindowManager] 监控已在运行中");
            return;
        }

        // 确保先初始化已存在的窗口
        initializeExistingWindows();

        log.info("[WindowManager] 开始监控，目标窗口数量: {}，当前窗口数量: {}",
                targetWindowCount, managedWindows.size());

        // 每5秒检查一次窗口数量
        monitorExecutor.scheduleAtFixedRate(this::checkWindows,
                0, MONITOR_INTERVAL, TimeUnit.SECONDS);
    }

    /**
     * 核心监控逻辑：检查是否需要启动新窗口
     */
    private void checkWindows() {
        try {
            // 清理无效窗口
            cleanupInvalidWindows();

            int currentCount = managedWindows.size();
            log.debug("[WindowManager] 当前窗口数量: {}/{}", currentCount, targetWindowCount);

            // 检查是否需要创建新窗口
            if (currentCount < targetWindowCount) {
                createNewWindowIfNeeded();
            }

        } catch (Exception e) {
            log.error("[WindowManager] 监控检查错误", e);
        }
    }

    /**
     * 创建新窗口（如果需要）
     */
    private void createNewWindowIfNeeded() {
        // 检查是否正在创建中
        if (!isCreating.compareAndSet(false, true)) {
            log.debug("[WindowManager] 正在创建窗口中，跳过");
            return;
        }

        try {
            // 检查创建冷却
            if (!checkCreationCooldown()) {
                return;
            }

            // 检查是否已有启动窗口
            if (hasExistingStartWindow()) {
                log.debug("[WindowManager] 已有启动窗口在处理中，等待其完成");
                return;
            }

            // 创建新的启动窗口
            createNewStartWindow();

        } catch (Exception e) {
            log.error("[WindowManager] 创建新窗口失败", e);
        } finally {
            isCreating.set(false);
            lastCreationTime.set(System.currentTimeMillis());
        }
    }

    /**
     * 检查创建冷却时间
     */
    private boolean checkCreationCooldown() {
        long lastTime = lastCreationTime.get();
        long currentTime = System.currentTimeMillis();

        if (lastTime > 0 && (currentTime - lastTime) < CREATION_COOLDOWN_MS) {
            log.debug("[WindowManager] 创建冷却中，跳过");
            return false;
        }
        return true;
    }

    /**
     * 检查是否已有启动窗口
     */
    private boolean hasExistingStartWindow() {
        for (IWindow window : managedWindows) {
            if (window instanceof StartWindow) {
                return true;
            }
        }
        return false;
    }

    /**
     * 创建新的启动窗口
     */
    private void createNewStartWindow() {
        try {
            log.info("[WindowManager] 创建新的启动窗口");

            // 创建空HWND的StartWindow，让它自己处理启动逻辑
            StartWindow startWindow = new StartWindow(new WinDef.HWND(Pointer.NULL));
            startWindow.setGameExePath(gameExePath);
            startWindow.start();

            managedWindows.add(startWindow);

            log.info("[WindowManager] 启动窗口任务已提交");

        } catch (Exception e) {
            log.error("[WindowManager] 创建启动窗口失败", e);
        }
    }

    /**
     * LoginWindow 转换为GameWindow
     */
    public void convertToGameWindow(LoginWindow loginWindow) {
        if (loginWindow == null || !managedWindows.contains(loginWindow)) {
            return;
        }

        try {
            GameWindow gameWindow = new GameWindow(loginWindow.getHwnd());
            managedWindows.remove(loginWindow);
            loginWindow.shutdown();
            managedWindows.add(gameWindow);
            log.info("[WindowManager] 成功转换窗口: {} -> {}", loginWindow.getId(), gameWindow.getId());
        } catch (Exception e) {
            log.error("[WindowManager] 转换窗口失败: {}", loginWindow.getId(), e);
        }
    }

    /**
     * StartWindow 转换为LogiWindow
     */
    @SneakyThrows
    public void convertToLoginWindow(StartWindow startWindow, long timeoutMs) {
        if (startWindow == null || !managedWindows.contains(startWindow)) {
            return;
        }

        managedWindows.remove(startWindow);
        startWindow.shutdown();

        long startTime = System.currentTimeMillis();
        long endTime = startTime + timeoutMs;

        while (System.currentTimeMillis() < endTime) {
            List<WinDef.HWND> windows = HwndUtil.findWindows(WINDOW_CLASS_GAME, GAME_TITLE);

            for (WinDef.HWND hwnd : windows) {
                if (isNewWindow(hwnd)) {
                    managedWindows.add(new LoginWindow(hwnd));
                }
            }
            Thread.sleep(500); // 增加等待间隔，减少CPU使用

            // 检查中断
            if (Thread.currentThread().isInterrupted()) {
                throw new InterruptedException("等待窗口被中断");
            }
        }
    }

    /**
     * 检查是否是新窗口（未被管理）
     */
    private boolean isNewWindow(WinDef.HWND hwnd) {
        synchronized (managedWindows) {
            return managedWindows.stream()
                    .noneMatch(window -> window.getHwnd().equals(hwnd));
        }
    }

    /**
     * 清理无效窗口
     */
    private void cleanupInvalidWindows() {
        synchronized (managedWindows) {
            Iterator<IWindow> iterator = managedWindows.iterator();
            int removedCount = 0;

            while (iterator.hasNext()) {
                IWindow window = iterator.next();
                if (!window.isValid()) {
                    log.info("[WindowManager] 移除无效窗口: {}", window.getId());
                    iterator.remove();
                    window.shutdown();
                    removedCount++;
                }
            }

            if (removedCount > 0) {
                log.info("[WindowManager] 清理了 {} 个无效窗口", removedCount);
            }
        }
    }

    /**
     * 验证游戏窗口
     */
    private boolean isValidGameWindow(WinDef.HWND hwnd) {
        return HwndUtil.isWindowVisible(hwnd) &&
                HwndUtil.isWindowEnabled(hwnd) &&
                HwndUtil.getWindowRectangle(hwnd).width > 100 &&
                HwndUtil.getWindowRectangle(hwnd).height > 100;
    }

    /**
     * 获取管理的窗口列表
     */
    public List<IWindow> getManagedWindows() {
        synchronized (managedWindows) {
            return Collections.unmodifiableList(new ArrayList<>(managedWindows));
        }
    }

    /**
     * 关闭管理器
     */
    public void shutdown() {
        log.info("[WindowManager] 开始关闭管理器");
        stopMonitoring();

        synchronized (managedWindows) {
            for (IWindow window : managedWindows) {
                try {
                    window.shutdown();
                } catch (Exception e) {
                    log.error("[WindowManager] 关闭窗口失败: {}", window.getId(), e);
                }
            }
            managedWindows.clear();
        }

        log.info("[WindowManager] 管理器已关闭");
    }

    /**
     * 停止监控
     */
    public void stopMonitoring() {
        if (!isMonitoring.getAndSet(false)) {
            return;
        }

        log.info("[WindowManager] 停止监控");
        monitorExecutor.shutdown();

        try {
            if (!monitorExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
                monitorExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            monitorExecutor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}